package com.xiyuan.smartutils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

/**
 * 验证码生成
 * @author xiyuan-lgz
 */
public final class Captchas {
    
    private static final String TABLES = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
    private static String generatorCode(Random random, int length) {
        StringBuilder buffer = new StringBuilder();
        for (int i = 0; i < length; i++) {
            buffer.append(TABLES.charAt(random.nextInt(TABLES.length())));
        }
        return buffer.toString();
    }
    
    public static class CaptchaConfig {
        private int type = 1;
        private int len = 4;
        private int width = 120;
        private int height = 50;
        
        public int getType() {
            return type;
        }
        
        public void setType(int type) {
            this.type = type;
        }
        
        public int getLen() {
            return len;
        }
        
        public void setLen(int len) {
            this.len = len;
        }
        
        public int getWidth() {
            return width;
        }
        
        public void setWidth(int width) {
            this.width = width;
        }
        
        public int getHeight() {
            return height;
        }
        
        public void setHeight(int height) {
            this.height = height;
        }
        
        final Random random = new Random(System.currentTimeMillis());
        
        public Random getRandom() {
            return random;
        }
    }
    
    public static String newCaptcha(OutputStream out, CaptchaConfig config) throws IOException {
        int width = config.getWidth();
        int height = config.getHeight();
        int len = config.getLen();
        Random random = config.getRandom();
        // 1、创建对象 验证码图片
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        
        // 2、美化图片
        // 2.1 填充背景色
        
        // 画笔对象,2D来旋转验证码字母
        Graphics2D g = (Graphics2D) image.getGraphics();
        // 设置画笔颜色
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, width, height);
        
        // 改变字体
        g.setFont(new Font("宋体", Font.BOLD, 35));
        String code = generatorCode(random, len);
        char[] arr = code.toCharArray();
        for (int i = 0; i < arr.length; i++) {
            // 将验证码偏转并写到画布上
            //  获取字符
            char ch = arr[i];
            int x = width / len * i;
            int y = height / 2;
            
            // 获取正负30的角度
            int angle = random.nextInt(60) - 30;
            double radian = angle * Math.PI / 180;
            // 设置验证码中的字体颜色
            // g.setColor(Color.BLUE);
            
            int red = 0;
            int green = 0;
            int blue = 0;
            
            int codeY = 32;
            // 得到随机产生的验证码数字
            // 产生随机的颜色分量来构造颜色值,使输出的每位数字的颜色值都不同
            red = random.nextInt(255);
            green = random.nextInt(255);
            blue = random.nextInt(255);
            // 用随机产生的颜色将验证码绘制到图像中
            g.setColor(new Color(red, green, blue));
            // 写验证码
            g.rotate(radian, x, y);
            // 把字母画在画布上
            // g.drawString(ch+"", x, y);
            g.drawString(String.valueOf(ch) + "", x, codeY);
            // 把每次旋转的再旋转回来
            g.rotate(-radian, x, y);
            // 每次向右移动20像素
            x += 15;
            
        }
        
        // 2.4随机产生20条干扰线 和 干扰蛋
        for (int i = 0; i < 10; i++) {
            g.setColor(new Color(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
            
            // 随机生成坐标点
            int x1 = random.nextInt(width);
            int x2 = random.nextInt(height);
            int y1 = random.nextInt(width);
            int y2 = random.nextInt(height);
            g.drawLine(x1, x2, y1, y2);
            
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            g.drawOval(x, y, 5, 5);
        }
        
        g.dispose();
        ImageIO.write(image, "gif", out);
        
        return code;
    }
}
